#include "Anx_tcp_select.h"

#include "Anx_socket.h"

#include "Anx_RTT.h"

const static char* TAG = "TCP_SELECT";

int select_socket = 0;
int client_sockets[TCP_MAX_CLIENTS] = { 0 };




/******************************************************************************
 * 描述  : 创建tcp客户端
 * 参数  : 无
 * 返回  : 无
******************************************************************************/
void tcp_select_task(const void* arg)
{
    int server_fd, max_fd, activity;
    struct sockaddr_in address;
    fd_set read_fds;

    //创建socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        Debug_log(TAG, "socket failed\r\n");
        vTaskDelete(NULL);
    }

    //设置地址重用
    int opt = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(TCP_LOCAL_PORT);

    if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0)
    {
        Debug_log(TAG, "bind failed\r\n");
        close(server_fd);
        vTaskDelete(NULL);
    }

    fcntl(server_fd, F_SETFL, O_NONBLOCK); //设置为非阻塞模式

    if (listen(server_fd, TCP_MAX_CLIENTS) < 0)
    {
        Debug_log(TAG, "listen failed\r\n");
        close(server_fd);
        vTaskDelete(NULL);
    }

    Debug_log(TAG, "TCP server listening on port %d\r\n", TCP_LOCAL_PORT);


    while (1)
    {
        FD_ZERO(&read_fds);
        FD_SET(server_fd, &read_fds);
        max_fd = server_fd;

        //添加已连接的客户端socket到集合
        for (int i = 0; i < TCP_MAX_CLIENTS; i++)
        {
            if (client_sockets[i] > 0)
            {
                FD_SET(client_sockets[i], &read_fds);
                if (client_sockets[i] > max_fd)
                    max_fd = client_sockets[i];
            }
        }

        //设置select超时时间
        struct timeval timeout = {
            .tv_sec = 0,
            .tv_usec = 100000 //100ms
        };

        activity = select(max_fd + 1, &read_fds, NULL, NULL, &timeout);
        if (activity < 0 && errno != EINTR)
        {
            Debug_log(TAG, "select error\r\n");
            // break;
        }

        //检查是否有新的连接请求
        if (FD_ISSET(server_fd, &read_fds))
        {
            int new_socket;
            struct sockaddr_in client_address;
            socklen_t addr_len = sizeof(client_address);

            new_socket = accept(server_fd, (struct sockaddr*)&client_address, &addr_len);
            if (new_socket < 0)
            {
                Debug_log(TAG, "accept failed\r\n");
                continue;
            }

            //将新连接的socket添加到客户端数组
            for (int i = 0; i < TCP_MAX_CLIENTS; i++)
            {
                if (client_sockets[i] == 0)
                {
                    client_sockets[i] = new_socket;
                    fcntl(new_socket, F_SETFL, O_NONBLOCK); //设置为非阻塞模式
                    Debug_log(TAG, "New connection, socket fd is %d, ip is : %s, port : %d\r\n",
                        new_socket,
                        inet_ntoa(client_address.sin_addr),
                        ntohs(client_address.sin_port));
                    break;
                }
            }
        }    //处理客户端数据
        for (int i = 0; i < TCP_MAX_CLIENTS; i++)
        {
            int sd = client_sockets[i];
            if (sd <= 0 || !FD_ISSET(sd, &read_fds))
                continue;

            char buffer[TCP_BUFFER_SIZE];
            int valread = recv(sd, buffer, sizeof(buffer), 0);
            if (valread > 0)
            {
                //处理接收到的数据
                buffer[valread] = '\0'; //确保字符串终止
                Debug_log(TAG, "Received from socket %d: %s\r\n", sd, buffer);

                //回显数据
                send(sd, buffer, valread, 0);
            }
            else if ((valread == 0) || (valread < 0 && errno != EAGAIN))
            {
                //连接关闭
                Debug_log(TAG, "Client disconnected, socket fd is %d\r\n", sd);
                close(sd);
                client_sockets[i] = 0;
            }
        }
        // taskYIELD();
    }
}



